package web

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	jwt "github.com/golang-jwt/jwt/v5"
	"net/http"
	"regexp"
	"time"
	"webook/internal/domain"
	"webook/internal/service"
)

var JwtKey = "moyn8y9abnd7q4zkq2m73yw8tu9j5ixm"

type UserHandler struct {
	srv           *service.UserService
	emailRegex    *regexp.Regexp
	passwordRegex *regexp.Regexp
}
type UserClaims struct {
	Id int64
	jwt.RegisteredClaims
}

// 创建Handler对象
func NewUserHandler(srv *service.UserService) *UserHandler {
	const (
		emailRegexPattern = `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
		// 简化密码正则表达式，仅检查长度和字符集
		passwordRegexPattern = `^[A-Za-z\d.$@$!%*#?&]{8,72}$`
	)
	return &UserHandler{
		srv:           srv,
		emailRegex:    regexp.MustCompile(emailRegexPattern),
		passwordRegex: regexp.MustCompile(passwordRegexPattern),
	}
}

// 注册接口
func (u *UserHandler) RegisterRoutes(server *gin.Engine) {
	server.POST("/users/signup", u.SignUp)
	server.POST("/users/login", u.Login)
	server.POST("/users/edit", u.Edit)
	server.GET("/users/profile", u.Profile)
}

// 登录 注册 修改 查询 四个路由处理方法
func (u *UserHandler) SignUp(ctx *gin.Context) {
	type SignUpReq struct {
		Email           string `json:"email"`
		Password        string `json:"password"`
		ConfirmPassword string `json:"confirmPassword"`
	}

	var req SignUpReq
	err := ctx.Bind(req)
	if err != nil {
		//Bind自动写好了
		return
	}
	isMatch := u.emailRegex.MatchString(req.Email)
	if isMatch == false {
		ctx.String(http.StatusOK, "邮箱格式不正确")
		return
	}
	isMatch = u.passwordRegex.MatchString(req.Password)
	if isMatch == false {
		ctx.String(http.StatusOK, "密码格式不正确")
		return
	}
	if req.Password != req.ConfirmPassword {
		ctx.String(http.StatusOK, "两次密码不一致")
		return
	}
	//数据库操作
	err = u.srv.SignUp(ctx, domain.User{
		Email:    req.Email,
		Password: req.Password,
	})
	if errors.Is(err, service.ErrUserDuplicateEmail) {
		ctx.String(http.StatusOK, "邮件重复")
		return
	}
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}

	ctx.String(http.StatusOK, "注册成功")
}

func (u *UserHandler) Login(ctx *gin.Context) {
	type LoginReq struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}

	var req LoginReq
	err := ctx.Bind(&req)
	if err != nil {
		return
	}

	//查询数据库
	var user domain.User
	user, err = u.srv.Login(ctx, req.Email, req.Password)
	if errors.Is(err, service.ErrInvalidUserOrPassword) {
		ctx.String(http.StatusOK, "邮箱或密码错误")
		return
	}
	if err != nil {
		ctx.String(http.StatusOK, "系统错误")
		return
	}

	//TODO:不用Session了 用jwt
	//session and cookie
	//sess := sessions.Default(ctx)
	//sess.Set("userId", user.Id)
	//sess.Options(sessions.Options{
	//	//60秒过期
	//	MaxAge: 60,
	//})
	//err = sess.Save()
	//if err != nil {
	//	ctx.String(http.StatusOK, "服务器异常")
	//	return
	//}

	//jwt

	//Claims 是一个结构体，用于存储 JWT 的声明信息。
	//Claims 结构体包含了 JWT 的标准声明信息，如 Issuer、Subject、ExpiresAt、IssuedAt 等。
	//Claims 结构体还可以包含自定义的声明信息，如 UserId、UserName 等。
	//Claims 结构体的实现方式有多种，如自定义结构体、结构体嵌套、结构体继承等。
	//Claims可以存储自定义的声明信息，如用户ID、用户名、角色、权限等。
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims{
		Id: user.Id,
		RegisteredClaims: jwt.RegisteredClaims{
			//过期时间
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute * 15)),
		},
	})
	tokenStr, err := token.SignedString([]byte(JwtKey))
	if err != nil {
		ctx.String(http.StatusOK, "系统异常")
		return
	}
	ctx.Header("X-Jwt-Token", tokenStr)

	fmt.Println(user)
	ctx.String(http.StatusOK, "登录成功")
}

func (u *UserHandler) Edit(ctx *gin.Context) {
	ctx.String(http.StatusOK, "Edit功能")
}
func (u *UserHandler) Profile(ctx *gin.Context) {
	ctx.String(http.StatusOK, "Profile功能")
}
